// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Author: Markus Gutschke

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include "cfg.h"
#include "check.h"
#include "ieee1284.h"
#include "json.h"
#include "misc.h"
#include "printer.h"
#include "proxyloop.h"
#include "stringprintf.h"


static char *getDefaultValue(struct JSON *json, const char *key,
                             const char *defValue, int *dirty) {
  check(json->type == J_OBJECT);
  struct JSON *value = (struct JSON *)getFromHashMap(&json->obj, key);
  if (value) {
    check(value->type == J_STRING);
    char *ret;
    check(ret = strdup(value->str));
    return ret;
  } else if (defValue) {
    *dirty = 1;
    updateJSONValue(json, key, "\"\"");
    struct JSON *str = (struct JSON *)getFromHashMap(&json->obj, key);
    check(str->str = realloc(str->str, strlen(defValue) + 1));
    char *ret;
    check(ret = strdup(strcpy(str->str, defValue)));
    return ret;
  }
  return NULL;
}

static void ignore(int signo) {
}

int main(int argc, char *argv[]) {
  signal(SIGPIPE, ignore);

  // Open the configuration file. It keeps state from previous runs and can
  // also be used by external utilities to configure the CloudPrint proxy.
  struct Cfg *cfg = newCfg(".pitsd", 1);
  struct JSON *cfgJSON = lockCfgAndGetJSON(cfg);
  int dirty = 0;

  /***/
  // These parameters are specific to the CloudPrint provider and must be
  // customized.
  const char *cloudPrintURL = getDefaultValue(cfgJSON, "cloudprint",
                                 "https://www.google.com/cloudprint/interface",
                                 &dirty);
  const char *oauth2URL     = getDefaultValue(cfgJSON, "oauth2",
                                  "https://accounts.google.com/o/oauth2/token",
                                  &dirty);

  // The same client id as used by the proxy inside Chrome (this should
  // be changed before deployment)
  const char *client_id     = getDefaultValue(cfgJSON, "clientId",
                                     "551556820943.apps.googleusercontent.com",
                                     &dirty);
  const char *client_secret = getDefaultValue(cfgJSON, "clientSecret",
                                              "u3/mp8CgLFxh4uiX1855/MHe",
                                              &dirty);
  /***/
  
  // Retrieve the id that we previously used to identify our proxy to the
  // cloud, or randomly generate a new unique identifier.
  const char *proxyNameNew = uniqueID();
  const char *proxyName = getDefaultValue(cfgJSON, "proxyName",
                                          proxyNameNew, &dirty);
  free((void *)proxyNameNew);

  // Flush configuration data to disk, if we made any changes
  if (dirty) {
    commitCfg(cfg);
    dirty = 0;
  } else {
    unlockCfg(cfg);
  }

  int numPrinters;
  struct Printer *printers  = registerAllPrinters(cfg, &numPrinters);

  // Main loop
  struct Proxy *proxy = newProxy(printers, numPrinters);
  proxyLoop(proxy);
  deleteProxy(proxy);

  // Clean up all resources
  free((void *)cloudPrintURL);
  free((void *)oauth2URL);
  free((void *)client_id);
  free((void *)client_secret);
  free((void *)proxyName);
  deleteCfg(cfg);

  return 0;
}
